package com.blue.jdbc;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.springframework.jdbc.support.KeyHolder;

import com.blue.core.dict.annotation.DictParser;
import com.blue.core.util.UUID;
import com.blue.jdbc.annotation.CacheColumn;
import com.blue.jdbc.annotation.CacheEntity;
import com.blue.jdbc.annotation.CacheId;
import com.blue.jdbc.annotation.CacheVersion;
import com.blue.jdbc.annotation.GeneratorType;
import com.blue.jdbc.annotation.Parser;

/**
 * 对象支持类
 * 
 * @author zhengj
 * @since 1.0 2011-4-1
 */
public class ObjectSupport
{
	private static ObjectSupport support = new ObjectSupport();

	private Parser parser = Parser.getInstance();
	private DictParser dictParser = DictParser.getInstance();

	private ObjectSupport()
	{
	}
	
	public static ObjectSupport getInstance()
	{
		return support;
	}

	/**
	 * 产生主键
	 * 
	 * @param map 映射
	 * @param clazz 类型
	 */
	public void generateId(Map<String, Object> map, Class<?> clazz)
	{
		CacheEntity cacheEntity = parser.parse(clazz);
		cacheEntity.getIdMap().forEach((k, v) ->
		{
			if (v.getGeneratorType() == GeneratorType.UUID)
			{
				String uuid = UUID.generator();
				map.put(v.getName(), uuid);
			}
		});
	}
	
	/**
	 * 取得对象的主键
	 * 
	 * @param obj 对象实例
	 * @return 映射
	 */
	public Map<String, Object> getId(Object obj)
	{
		Map<String, Object> map = new HashMap<>();
		CacheEntity cacheEntity = parser.parse(obj.getClass());
		cacheEntity.getIdMap().forEach((k, v) ->
		{
			try
			{
				Method getter = v.getGetterMethod();
				map.put(k, getter.invoke(obj));
			}
			catch (Exception e)
			{
				throw new IllegalArgumentException(e);
			}
		});
		
		return map;
	}

	/**
	 * 设置对象主键
	 * 
	 * @param key
	 * @param object
	 */
	public void setId(KeyHolder key, Object object)
	{
		CacheEntity cacheEntity = parser.parse(object.getClass());
		cacheEntity.getIdMap().forEach((k, v) ->
		{
			try
			{
				if (v.getGeneratorType() == GeneratorType.INCREMENT)
				{
					Method setter = v.getSetterMethod();
					Number id = key.getKey();
					if (v.getField().getType() == Long.class || v.getField().getType() == long.class)
						setter.invoke(object, id.longValue());
					else if (v.getField().getType() == Integer.class || v.getField().getType() == int.class)
						setter.invoke(object, id.intValue());
				}
			}
			catch (Exception e)
			{
				throw new IllegalArgumentException(e);
			}
		});
		
	}

	/**
	 * 设置映射主键
	 * 
	 * @param key
	 * @param map
	 * @param clazz
	 */
	public void setId(KeyHolder key, Map<String, Object> map, Class<?> clazz)
	{
		CacheEntity cacheEntity = parser.parse(clazz);
		cacheEntity.getIdMap().forEach((k, v) ->
		{
			if (v.getGeneratorType() == GeneratorType.INCREMENT)
			{
				map.put(v.getName(), key.getKey());
			}
		});
	}

	/**
	 * 对象转换为映射
	 * 
	 * @param map
	 * @param object
	 */
	public void objectToMap(Map<String, Object> map, Object object, boolean update)
	{
		if (object == null)
			return;

		CacheEntity cacheEntity = parser.parse(object.getClass());
		try
		{
			for (Map.Entry<String, CacheId> entry : cacheEntity.getIdMap().entrySet())
			{
				CacheId cacheId = entry.getValue();
				GeneratorType type = cacheId.getGeneratorType();
				if (update && type == GeneratorType.INCREMENT)
					continue;
				
				Method getter = cacheId.getGetterMethod();
				Object val = this.convert(getter.invoke(object));

				if ("".equals(val))
					val = null;

				map.put(cacheId.getName(), val);
			}
			
			for (Map.Entry<String, CacheColumn> entry : cacheEntity.getColumnMap().entrySet())
			{
				CacheColumn cacheColumn = entry.getValue();
				Method getter = cacheColumn.getGetterMethod();
				Object val = this.convert(getter.invoke(object));

				if ("".equals(val))
					val = null;

				map.put(cacheColumn.getName(), val);
			}
			
			for (Map.Entry<String, CacheColumn> entry : cacheEntity.getExtraMap().entrySet())
			{
				CacheColumn cacheColumn = entry.getValue();
				Method getter = cacheColumn.getGetterMethod();
				Object val = this.convert(getter.invoke(object));

				if ("".equals(val))
					val = null;

				map.put(cacheColumn.getName(), val);
			}
			CacheVersion cacheVersion = cacheEntity.getVersion();
			if (cacheVersion != null)
			{
				Method getter = cacheVersion.getGetterMethod();
				Object val = getter.invoke(object);
				
				if (update && val == null)
					val = 1;
				
				map.put(cacheVersion.getName(), val);
			}
		}
		catch (Exception e)
		{
			throw new IllegalArgumentException(e);
		}
	}

	private Object convert(Object val)
	{
		if (val == null)
			return null;
		
		Class<?> clazz = val.getClass();
		if (clazz.isEnum())
			return dictParser.getFromObject(val);
		
		return val;
	}
	
}
